-
Notifications
You must be signed in to change notification settings - Fork 286
Improve handling of parity integer #344
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
I agree that Even/Odd would be nicer in general but:
Parity should mean 0 is even. But yeah, I believe this is the problem with this change. rust-secp256k1 should be compatible with rust-secp256k1, and if upstream uses a parity bit, then we should do the same. Because only then users can be sure that if the bit is the same, they get the same result on rust-secp256k1 and on secp256k1. Maybe we can convince upstream to rename parity to |
Thanks for the review @real-or-random. I get your intention, users of Would you be happy with something like this:
|
nit, boolean values don't exist in C89, so this int actually is equivalent to a bool in rust as it is documented to be used as a bool (only 1/0) I personally wouldn't be against adding an enum, but I'd prefer if we can somehow not expose "even/odd" terminology to the user at all and somehow create an abstraction above this, as users IMO shouldn't know what even/odd means |
concept ACK using an enum for this. @tcharding is right that we already change the type from an Edit: oh, I misunderstood. I thought this was talking about key compressedness rather than parity. For parity I also think we should have an enum, but it needs to have explicit conversion functions between the numeric value (which is encoded in some places) and the enum. |
The import statements can be simplified by using an import wildcard (`super::*`). While we are at it put them in std, external crate, this crate order.
There are currently two unit tests in the `schnorr` module that are testing keys from the `key` module. This is possible because the tests are only testing the public interface, none the less they are better placed in the `key` module.
We have two `tweak_add_assign` methods (one for keypair and one for x-only pubkey). Both check the return value from a FFI function call. We can make both sites uniform to _slightly_ reduce cognitive load when reading the code. Use C style code to make it obvious to readers that this is basically C code.
@apoelstra can you please confirm that I've got all the encodings you refer to. I grepped for the function names involved and I believe I've got them all. |
Two functions in the FFI secp code return and accept a parity int. Currently we are manually converting this to a bool. Doing so forces readers of the code to think what the bool means even though understanding this bool is not needed since in is just passed back down to the FFI code. We can abstract this away by using an opaque type to hold the original int and not converting it to a boolean value. Add 'Return' and 'Error' sections to `tweak_add_assign` while fixing the docs to describe the new opaque parity type.
It is not immediately apparent what 'err == 1' means, one must determine that the FFI function call returns 1 for success. We can help readers of the code by adding a 'Return' section to the method documentation. Add trailing full stop to method docs initial line also.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ACK ede114f
This looks good to me. I haven't been involved with this API upstream so I'm probably not the best person to ask about having gotten all the conversion sites, but I think you did. (I grepped for some variations of {1}
or {true}
which would indicate an int->boolean conversion, and didn't find any.)
I actually liked that it was a single byte and that we didn't expose that |
I wouldn't mind changing the conversion function to go to/from a |
In rust-bitcoin, i32::from(self.output_key_parity) as u8 | self.leaf_version.as_u8() This is not the end of the world. Maybe in the next release, we can have a custom enum |
I think a u8 would be more conceptually clear. |
Why not a custom enum? |
post merge review: I'm not entirely convinced that a opaque type is useful here. You can't even XOR two parities which seems to be no so uncommon in advanced signing constructions. (If more is added to tweaking, e.g., musig). Not sure if really the user needs to access the value but on the other hand, I don't see how this opaque value is any safer than a bool. |
We could implement xor on this type. That's a pretty good idea. @real-or-random 'because a bool has no intrinsic meaning and does not "naturally" map to the two parity classes of elliptic curve points. |
In which case, we should update the constructors From to be fallible ones. |
So I think, for now we can simply
And we can do all this in a minor release. Later we can replace the underlying type with an enum so users can directly see "even" or "odd". |
So shell we have a point release addressing this together with #364? |
Yep |
Two functions in the FFI secp code return and accept a parity integer.
Currently we are manually converting this to a bool. Doing so forces readers of the code to think what the bool means even though understanding this value is not needed since in is just passed back down to the FFI code.
We initially tried to solve this issue by adding an enum, discussion below refers to that version. Instead of an enum we can solve this issue by adding an opaque type that holds the parity value returned by the FFI function call and then just pass it back down to FFI code without devs needing to know what the value should be. This fully abstracts the value away and removes the boolean conversion code which must otherwise be read by each dev.
tweak_add_assign
)